﻿using System;
using RayDen.Library.Core.Primitives;

namespace RayDen.Library.Components.Color
{
    public class RadianceEvaluationBase
    {
        protected RadianceEvaluationBase()
        {
            
        }

        protected RadianceEvaluationBase(RadianceEvaluationBase b)
        {
            
        }
    }

    public abstract class RadianceEvaluationBase<TValue> : RadianceEvaluationBase , IRadianceEvaluation
    {
        protected internal TValue Spectra;

        protected RadianceEvaluationBase(ref TValue spc)
        {
            this.Spectra = spc;
        }

        protected RadianceEvaluationBase(TValue spc)
        {
            this.Spectra = spc;
        }

        protected RadianceEvaluationBase(RadianceEvaluationBase<TValue> val)
        {
            this.Spectra = val.Spectra;
        }

        public IRadianceEvaluation Mul(IRadianceEvaluation value)
        {
            if (value is RadianceEvaluationBase<TValue>)
            {
                return this.Multiply((value as RadianceEvaluationBase<TValue>));
            }
            else
            {
                return Convert(value).Mul(this);
            }
        }

        public IRadianceEvaluation Add(IRadianceEvaluation value)
        {
            if (value is RadianceEvaluationBase<TValue>)
            {
                return this.Add((value as RadianceEvaluationBase<TValue>));
            }
            else
            {
                return Convert(value).Add(this);
            }
        }

        public abstract IRadianceEvaluation Mul(float value);
        public abstract IRadianceEvaluation Div(float value);
        void ISpectrum.Mul(float s)
        {
            this.Mul(s);
        }

        public void Mul(ref ISpectrum s)
        {
            throw new NotImplementedException();
        }

        public abstract IRadianceEvaluation Add(float value);

        public IRadianceEvaluation MAdd(IRadianceEvaluation r, float f)
        {
            return this.Add(r.Mul(f));
        }

        public IRadianceEvaluation MAdd(IRadianceEvaluation r, IRadianceEvaluation f)
        {
            return this.Add(r.Mul(f));
        }


        public abstract void ToRgbSpectrum(out RgbSpectrum result);
        public abstract bool IsBlack { get; protected set; }
        void ISpectrum.Div(float d)
        {
            this.Div(d);
        }

        public abstract float[] ToArray();


        protected abstract RadianceEvaluationBase<TValue> Multiply(RadianceEvaluationBase<TValue> val);
        protected abstract RadianceEvaluationBase<TValue> Add(RadianceEvaluationBase<TValue> val);

      

        protected virtual IRadianceEvaluation Convert(IRadianceEvaluation val)
        {
            return val;
        }

        public abstract IRadianceEvaluation Clone();



        
    }


    public class RadianceFactory
    {
        public static bool SpectralSampling { get; set; }

        public static IRadianceEvaluation Zero
        {
            get { return SpectralSampling ? (IRadianceEvaluation) SpectralRadiance.Zero : RgbRadiance.Zero; }
        }

        public static IRadianceEvaluation Unit
        {
            get { return SpectralSampling ? (IRadianceEvaluation)SpectralRadiance.Unit : RgbRadiance.Unit; }
        }
    }

}
